import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

class Bill {
    private Date date;
    private double amount;
    private String category;
    private String note;

    public Bill(Date date, double amount, String category, String note) {
        this.date = date;
        this.amount = amount;
        this.category = category;
        this.note = note;
    }

    public Date getDate() {
        return date;
    }

    public double getAmount() {
        return amount;
    }

    public String getCategory() {
        return category;
    }

    public String getNote() {
        return note;
    }
}

class Income extends Bill {
    public Income(Date date, double amount, String category, String note) {
        super(date, amount, category, note);
        if (amount <= 0) {
            throw new IllegalArgumentException("Income amount must be positive.");
        }
    }
}

class Expense extends Bill {
    public Expense(Date date, double amount, String category, String note) {
        super(date, amount, category, note);
        if (amount <= 0) {
            throw new IllegalArgumentException("Expense amount must be positive.");
        }
    }
}

class BillManager {
    private List<Income> incomes = new ArrayList<>();
    private List<Expense> expenses = new ArrayList<>();
    private Scanner scanner = new Scanner(System.in);
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    public void recordIncome() {
        try {
            System.out.print("请输入收入信息: ");
            System.out.print("日期(yyyy-MM-dd): ");
            Date date = dateFormat.parse(scanner.nextLine());
            System.out.print("金额: ");
            double amount = Double.parseDouble(scanner.nextLine());
            System.out.print("类别（如工资、奖金等）: ");
            String category = scanner.nextLine();
            System.out.print("备注: ");
            String note = scanner.nextLine();
            incomes.add(new Income(date, amount, category, note));
            System.out.println("收入已成功记录！");
        } catch (ParseException e) {
            System.out.println("错误日期");
        } catch (NumberFormatException e) {
            System.out.println("错误金额");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }

    public void recordExpense() {
        try {
            System.out.print("请输入支出信息: ");
            System.out.print("日期(yyyy-MM-dd): ");
            Date date = dateFormat.parse(scanner.nextLine());
            System.out.print("金额: ");
            double amount = Double.parseDouble(scanner.nextLine());
            System.out.print("类别（如工资、奖金等）: ");
            String category = scanner.nextLine();
            System.out.print("备注: ");
            String note = scanner.nextLine();
            expenses.add(new Expense(date, amount, category, note));
            System.out.println("支出已成功记录！");
        } catch (ParseException e) {
            System.out.println("错误日期");
        } catch (NumberFormatException e) {
            System.out.println("错误金额.");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }

    public void displayBills() {
        System.out.println("收入:");
        for (Income income : incomes) {
            System.out.printf("日期: %s, 金额: %.2f, 类型: %s, 备注: %s%n",
                    dateFormat.format(income.getDate()), income.getAmount(), income.getCategory(), income.getNote());
        }
        System.out.println("支出:");
        for (Expense expense : expenses) {
            System.out.printf("日期: %s, 金额: %.2f, 类型: %s, 备注: %s%n",
                    dateFormat.format(expense.getDate()), expense.getAmount(), expense.getCategory(), expense.getNote());
        }
    }

    public void queryBills() {
        System.out.println("1.按照日期查询");
        System.out.println("2.按照日期范围查询");
        System.out.println("3.按照类别查询");
        System.out.print("输入选择: ");
        int choice = Integer.parseInt(scanner.nextLine());
        switch (choice) {
            case 1:
                queryByDate();
                break;
            case 2:
                queryByDateRange();
                break;
            case 3:
                queryByCategory();
                break;
            default:
                System.out.println("错误选项.");
        }
    }

    private void queryByDate() {
        try {
            System.out.print("输入日期(yyyy-MM-dd): ");
            Date date = dateFormat.parse(scanner.nextLine());
            System.out.println("收入:");
            for (Income income : incomes) {
                if (date.equals(income.getDate())) {
                    System.out.printf("日期: %s, 金额: %.2f, 类型: %s, 备注: %s%n",
                            dateFormat.format(income.getDate()), income.getAmount(), income.getCategory(), income.getNote());
                }
            }
            System.out.println("支出:");
            for (Expense expense : expenses) {
                if (date.equals(expense.getDate())) {
                    System.out.printf("日期: %s, 金额: %.2f, 类型: %s, 备注: %s%n",
                            dateFormat.format(expense.getDate()), expense.getAmount(), expense.getCategory(), expense.getNote());
                }
            }
        } catch (ParseException e) {
            System.out.println("Invalid date format. Please use yyyy-MM-dd.");
        }
    }

    private void queryByDateRange() {
        try {
            System.out.print("Enter start date (yyyy-MM-dd): ");
            Date startDate = dateFormat.parse(scanner.nextLine());
            System.out.print("Enter end date (yyyy-MM-dd): ");
            Date endDate = dateFormat.parse(scanner.nextLine());
            System.out.println("收入:");
            for (Income income : incomes) {
                if (income.getDate().compareTo(startDate) >= 0 && income.getDate().compareTo(endDate) <= 0) {
                    System.out.printf("日期: %s, 金额: %.2f, 类型: %s,备注: %s%n",
                            dateFormat.format(income.getDate()), income.getAmount(), income.getCategory(), income.getNote());
                }
            }
            System.out.println("支出:");
            for (Expense expense : expenses) {
                if (expense.getDate().compareTo(startDate) >= 0 && expense.getDate().compareTo(endDate) <= 0) {
                    System.out.printf("日期: %s, 金额: %.2f, 类型: %s, 备注: %s%n",
                            dateFormat.format(expense.getDate()), expense.getAmount(), expense.getCategory(), expense.getNote());
                }
            }
        } catch (ParseException e) {
            System.out.println("Invalid date format. Please use yyyy-MM-dd.");
        }
    }

    private void queryByCategory() {
        System.out.print("Enter category: ");
        String category = scanner.nextLine();
        System.out.println("收入:");
        for (Income income : incomes) {
            if (category.equals(income.getCategory())) {
                System.out.printf("日期: %s, 金额: %.2f, 类型: %s,备注: %s%n",
                        dateFormat.format(income.getDate()), income.getAmount(), income.getCategory(), income.getNote());
            }
        }
        System.out.println("Expenses:");
        for (Expense expense : expenses) {
            if (category.equals(expense.getCategory())) {
                System.out.printf("日期: %s, 金额: %.2f, 类型: %s,备注: %s%n",
                        dateFormat.format(expense.getDate()), expense.getAmount(), expense.getCategory(), expense.getNote());
            }
        }
    }

    public void manageBudget() {
        System.out.print("设置每个月支出的预算限额: ");
        double budgetLimit = Double.parseDouble(scanner.nextLine());
        double totalExpenses = 0;
        for (Expense expense : expenses) {
            totalExpenses += expense.getAmount();
        }
        double remainingBudget = budgetLimit - totalExpenses;
        System.out.printf("剩余可用预算: %.2f%n", remainingBudget);
    }

    public void monthlyStatistics() {
        double totalIncome = incomes.stream().mapToDouble(Income::getAmount).sum();
        double totalExpense = expenses.stream().mapToDouble(Expense::getAmount).sum();
        System.out.printf("总收入: %.2f%n", totalIncome);
        System.out.printf("总支出: %.2f%n", totalExpense);
    }

    public void showMenu() {
        while (true) {
            System.out.println("1. 记录收入");
            System.out.println("2. 记录支出");
            System.out.println("3.查看所有账单");
            System.out.println("4.查询账单");
            System.out.println("5.设置月度预算");
            System.out.println("6.查看月度统计报告");
            System.out.println("7.退出系统");
            System.out.print("请输入选项序号: ");
            int choice = Integer.parseInt(scanner.nextLine());
            switch (choice) {
                case 1:
                    recordIncome();
                    break;
                case 2:
                    recordExpense();
                    break;
                case 3:
                    displayBills();
                    break;
                case 4:
                    queryBills();
                    break;
                case 5:
                    manageBudget();
                    break;
                case 6:
                    monthlyStatistics();
                    break;
                case 7:
                    System.out.println("Exiting...");
                    scanner.close();
                    return;
                default:
                    System.out.println("错误选项，请重试.");
            }
        }
    }
}
public class git1 {
    public static void main(String[] args) {
        BillManager manager = new BillManager();
        manager.showMenu();
    }
}
